home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / NLoad / UDPLoadView.m < prev   
Encoding:
Text File  |  1991-04-12  |  5.5 KB  |  191 lines

  1. #include <c.h>
  2. #include <fcntl.h>
  3. #include <libc.h>
  4. #include <netdb.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <utmp.h>
  9.  
  10. #include <arpa/inet.h>
  11.  
  12. #include <netinet/in.h>
  13.  
  14. #include <sys/param.h>
  15. #include <sys/stat.h>
  16. #include <sys/socket.h>
  17. #include <sys/time.h>
  18. #include <sys/types.h>
  19.  
  20. #import "UDPLoadView.h"
  21. #import "NLoadCommon.h"
  22.  
  23. @implementation UDPLoadView
  24.  
  25. /*---------------------------------------------------------------------------
  26. Besides creating the new frame, initialize variables to default settings.
  27. With the addition of the RPC/UDP support, some new variables were added.
  28. These variables, initial settings, and impact of the settings follow:
  29.  
  30.                   Initial
  31.     Variable      Setting   Comment
  32.     hostName      NULL      overridden later to host name,
  33.     nErrors       MAX...    forces the view white if the first client/server
  34.                             call fails; then records # consecutive errors,
  35.                             turning the view white after MAXERRORS,
  36.     udpSocket     -1        forces initial udpClient call to create socket,
  37.     waitSeconds   WS..      default seconds to wait on remote server
  38.                             (can be overridden by defaults data base)
  39. -----------------------------------------------------------------------------*/
  40.  
  41. - initFrame:(const NXRect *) frameRect
  42. {
  43.     const char *string;
  44.     
  45.     waitSecs = WAITSECONDS;
  46.     
  47.     if ((string = getDefault("HostsWaitSeconds")) && sscanf(string, "%d", &waitSecs) != 1)
  48.         waitSecs = WAITSECONDS;
  49.  
  50.     udpSocket = -1;
  51.     
  52.     return [super initFrame:frameRect];
  53. }
  54.  
  55. - startTimer
  56. {
  57.     const char *string;
  58.     int time = REMOTEUPDATE;
  59.  
  60.     if ((string = getDefault("RemoteUpdateSeconds")) && sscanf(string, "%d", &time) != 1)
  61.         time = REMOTEUPDATE;
  62.     
  63.     timedEntry = DPSAddTimedEntry((double) time, (DPSTimedEntryProc) &timer, self, NX_BASETHRESHOLD);
  64.     
  65.     return self;
  66. }
  67.  
  68. /*---------------------------------------------------------------------------
  69. This code is used for remote hosts that do not have RPC support.  A dedicated
  70. load server must run on the remote hosts.  Most sites will never execute this
  71. code.
  72.  
  73. If we do not have a UDP socket upon entry, we must go through the laborious
  74. task of setting one up.  This requires that we create the socket, set it
  75. up for no delay, and bind it.
  76.  
  77. Once we have a valid UDP socket, we send a tickler UDP packet to the remote
  78. host.  We wait a short period of time for the remote host to respond.  We
  79. expect the server to reply with a string of the form:
  80.                 "hostname load1 load5 load15 scale"
  81. -----------------------------------------------------------------------------*/
  82. - loadAverage:(long *)vector loadScale:(int *)scale
  83. {
  84.     char buf[BUFSIZ];
  85.     char *bufPtr;
  86.  
  87.     int i;
  88.     int nBytes;
  89.     int newSocket;
  90.     int temp;
  91.  
  92.     struct sockaddr_in clientSocket;
  93.     struct hostent *hp;
  94.  
  95.     if (udpSocket < 0) {
  96.         if ((hp = gethostbyname((char *) hostName)) == NULL) {
  97.             fprintf(stderr, "Unknown host '%s'.\n", hostName);
  98.             return nil;
  99.             }
  100.  
  101.         /* Set up the UDP server socket.
  102.          * Client and server both use UDPSERVERPORT.
  103.          */
  104.         bzero((char *) &udpServerSocket, sizeof(udpServerSocket));
  105.         udpServerSocket.sin_family = AF_INET;
  106.  
  107.         bcopy(hp->h_addr, &udpServerSocket.sin_addr.s_addr, hp->h_length);
  108.         udpServerSocket.sin_port = htons(UDPSERVERPORT);
  109.  
  110.         /* Create the client's socket.  Set this socket for no delay so
  111.          * we can time out if the server is down or slow in responding.
  112.          * Bind the socket to appropriate protocol, host, and port.
  113.          */
  114.         if ((newSocket = socket(AF_INET, SOCK_DGRAM, 0)) == CERROR) {
  115.             fprintf (stderr,"Can not open datagram socket.\n");
  116.             return nil;
  117.             }
  118.     
  119.         if (fcntl(newSocket, F_SETFL, FNDELAY) == CERROR) {
  120.             fprintf(stderr, "fcntl F_SETFL, FNDELAY error.\n");
  121.             close(newSocket);
  122.             return nil;
  123.             }
  124.     
  125.         bzero((char *) &clientSocket, sizeof(clientSocket));    /* zero out */
  126.         clientSocket.sin_family = AF_INET;
  127.         clientSocket.sin_addr.s_addr = htonl(INADDR_ANY);
  128.         clientSocket.sin_port = htons(0);
  129.  
  130.         if (bind(newSocket, (struct sockaddr *) &clientSocket, sizeof(clientSocket)) == CERROR) {
  131.             fprintf (stderr, "Unable to bind the local address.\n");
  132.             close (newSocket);
  133.             return nil;
  134.             }
  135.  
  136.         udpSocket = newSocket;    /* Success.  Finalize the deal! */
  137.         }    
  138.  
  139.     /* Send a tickler character to the remote server to wake it up.  The
  140.      * server should return a string with the host name, load values, and
  141.      * scale value.
  142.      */
  143.     if (sendto(udpSocket, "T", 1, 0, (struct sockaddr *) &udpServerSocket, sizeof(udpServerSocket)) == CERROR) {
  144.         close (udpSocket);
  145.         udpSocket = -1;        /* Forces initialization at next entry. */
  146.         return nil;
  147.         }
  148.  
  149.     /* Patiently wait "waitSecs" seconds for the remote server to respond.  We
  150.      * throw away any packets we receive from servers that we don't expect to
  151.      * hear from.
  152.      */
  153.     nBytes = 0;
  154.     for (i = 0; i < waitSecs && nBytes <= 0 ; i++) {
  155.         sleep (1);
  156.  
  157.         nBytes = recvfrom(udpSocket, buf, BUFSIZ-1, 0, NULL, &temp);
  158.  
  159.         if (nBytes > 0 && strncmp (hostName, buf, strlen(hostName)) != 0) nBytes = 0;
  160.         }        
  161.  
  162.     if (nBytes <= 0) {
  163.         close(udpSocket);
  164.         udpSocket = -1;        /* Forces initialization at next entry. */
  165.         return nil;
  166.         }
  167.       
  168.     /* At this point we have a response from the server.  The server should
  169.      * have returned a string in the form "hostname load1 load5 load15 scale".
  170.      * Extract the values and return.
  171.      */
  172.     buf[nBytes] = '\0';
  173.  
  174.     bufPtr = strtok (buf, " ");
  175.     bufPtr = strtok (NULL, " "); /* Skip the slave's host name */
  176.  
  177.     for (i = 0; i < QUEUES; i++) {
  178.         if (bufPtr == NULL) break;
  179.  
  180.         vector[i] = atoi(bufPtr);
  181.         bufPtr = strtok (NULL, " ");          
  182.         }
  183.  
  184.     if (bufPtr == NULL) return nil;
  185.  
  186.     *scale = atoi (bufPtr);
  187.     return self;
  188. }
  189.  
  190. @end
  191.